package com.cj.file.service.impl;

import com.cj.common.constant.Constant;
import com.cj.common.exception.BaseException;
import com.cj.common.utils.StrUtil;
import com.cj.file.constant.FileConstant;
import com.cj.file.entity.FileProperties;
import com.cj.file.entity.ServiceProperties;
import com.cj.file.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @Author cheng jun
 * @Description:
 * @Date 2021/7/9 17:30
 */
@Service("onlineFileServiceImpl")
@EnableConfigurationProperties({FileProperties.class, ServiceProperties.class})
@Slf4j
public class OnlineFileServiceImpl implements FileService {

    @Resource
    private FileProperties fileProperties;
    @Resource
    private ServiceProperties serviceProperties;

    @Override
    public Map<String, Object> upLoad(MultipartFile file) {
        // 获取文件原始名称
        String originalFilename = file.getOriginalFilename();

        // 获取文件后缀
        String extension = FilenameUtils.getExtension(originalFilename);

        // 新的名称
        String newFilename = new SimpleDateFormat("yyyyMMddhhmmss").format(new Date()) +
                UUID.randomUUID().toString().replace("-", "") + "." + extension;

        // 获取文件大小
        long fileSize = file.getSize();
        if (fileSize > this.sizeConvert()) {
            throw new BaseException("文件太大");
        }

        // 获取文件类型
        String fileType = file.getContentType();

        // 存储路径
        String dirPath = new SimpleDateFormat("yyyyMMdd").format(new Date());
        try {
            // 根据日期生成目录
            String dateDirPath = ResourceUtils.getURL("file/src/main/resources/static/files/").getPath() + dirPath;
            File dateDir = new File(dateDirPath);
            if (!dateDir.exists()) {
                dateDir.mkdirs();
            }
            // 文件上传
            file.transferTo(new File(dateDir, newFilename));
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BaseException(e.getMessage());
        }

        Map<String, Object> map = new HashMap<>();
        map.put("originalName", originalFilename);
        map.put("newName", newFilename);
        map.put("extension", extension);
        map.put("size", fileSize);
        map.put("type", fileType);
        map.put("path", dirPath);
        return map;
    }

    @Override
    public void downLoad(Map<String, Object> map, HttpServletResponse response) {
        Assert.notNull(map.get("path"), "文件路径不能为空");
        Assert.notNull(map.get("newName"), "新的名字不能为空");

        FileInputStream fileInputStream = null;
        ServletOutputStream servletOutputStream = null;
        try{
            // 获取文件输入流
            String realPath = ResourceUtils.getURL("file/src/main/resources/static/files/").getPath() +
                    map.get("path");
            fileInputStream = new FileInputStream(new File(realPath, String.valueOf(map.get("newName"))));

            // 设置下载名(attachment:下载，inline：在线打开)
            response.setHeader("content-disposition", "attachment" + ";fileName=" +
                    URLEncoder.encode("存储旧名字", "UTF-8"));
            // 获取响应输出流
            servletOutputStream = response.getOutputStream();

            // 第四种方式：文件拷贝
            IOUtils.copy(fileInputStream, servletOutputStream);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BaseException(e.getMessage());
        } finally {
            // 关闭输入输出流
            try {
                IOUtils.close(fileInputStream);
                IOUtils.close(servletOutputStream);
            } catch (IOException e) {
                log.error(e.getMessage());
                throw new BaseException(e.getMessage());
            }
        }
    }

    @Override
    public String fileDisplay(Map<String, Object> map) {
        Assert.notNull(map.get("filePath"), "文件路径不能为空");
        Assert.notNull(map.get("newName"), "文件名称不能为空");

        // 获取文件路径
        String path;
        try {
            // 获取文件路径
            path = Constant.HTTP_PROTOCOL + "://" + StrUtil.getLocalIp() + ":" + serviceProperties.getPort() +
                    "/files/" + map.get("filePath") + "/" + map.get("newName");
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BaseException(e.getMessage());
        }

        return path;
    }

    @Override
    public boolean fileDelete(Map<String, Object> map) {
        Assert.notNull(map.get("filePath"), "文件路径不能为空");
        Assert.notNull(map.get("newName"), "文件名称不能为空");

        // 获取文件路径
        String path;
        try {
            path = ResourceUtils.getURL("file/src/main/resources/static/files/").getPath() +
                    map.get("filePath");
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BaseException(e.getMessage());
        }
        // 删除
        File file = new File(path, String.valueOf(map.get("newName")));
        boolean flag = false;
        if (file.exists()) {
            flag = file.delete();
        }
        return flag;
    }

    @Override
    public void htmlToWorldExport(Map<String, Object> map, HttpServletResponse response) {

    }

    @Override
    public void worldExport(Map<String, Object> map, HttpServletResponse response) {

    }

    @Override
    public boolean getIfInclude(String jd, String wd) {
        return false;
    }

    @Override
    public Map<String, Object> shpFileImportCalculate(MultipartFile file) {
        return null;
    }

    public long sizeConvert() {
        // 获取最大存储大小
        String storageSize = fileProperties.getSize();

        // 获取数据单位
        String unit = storageSize.substring(storageSize.length() - 1);
        int size = Integer.parseInt(storageSize.substring(0, storageSize.length() - 1));
        long bSize = 0L;
        switch(unit){
            case FileConstant.G :
                bSize = size * 1024 * 1024 * 1024;
                break;
            case FileConstant.M :
                bSize = size * 1024 * 1024;
                break;
            case FileConstant.K :
                bSize = size * 1024;
                break;
            case FileConstant.B :
                bSize = size;
                break;
            default :
        }

        return bSize;
    }
}
